<?php

namespace utils;

use Firebase\JWT\JWT;
use think\facade\Cache;
use think\facade\Env;
use app\services\CacheServices;

/**
 * Jwt
 * Class JwtAuth
 * @package crmeb\utils
 */
class JwtAuth
{

    /**
     * token
     * @var string
     */
    protected $token;

    /**
     * 获取token
     * @param int $uid
     * @param array|null $user
     * @param string $type
     * @param array $params
     * @return array
     */
    public function getToken(int $uid, ?array $user = null, string $type = '1', array $params = []): array
    {
        $host = app()->request->host();
        $time = time();
        $params += [
            'iss' => $host,
            'aud' => $host,
            'iat' => $time,
            'nbf' => $time,
            'exp' => strtotime('+ 168hour'),
            'user' => $user,
        ];
        $params['jti'] = [
            'uid' => $uid,
            'type' => $type
        ];
        $token = JWT::encode($params, Env::get('app.app_key', 'default'));
        return compact('token', 'params');
    }

    /**
     * 解析token
     * @param string $jwt
     * @return array
     */
    public function parseToken(string $jwt): array
    {

        $this->token = $jwt;
        list($headb64, $bodyb64, $cryptob64) = explode('.', $this->token);
        $payload = JWT::jsonDecode(JWT::urlsafeB64Decode($bodyb64));
        return [$payload->jti->uid, $payload->jti->type];
    }

    /**
     * 验证token
     * @param string $token
     * @return array
     */
    public function verifyToken(string $token): array
    {
        JWT::$leeway = 60;
        $jwt = JWT::decode($token, Env::get('app.app_key', 'default'), array('HS256'));
        $jwt = $this->object_array($jwt);
        return $jwt;
    }



    /**
     * 对象转数组
     */
    function object_array ($array)
    {
        if (is_object($array)) {
            $array = (array)$array;
        }
        if (is_array($array)) {
            foreach ($array as $key => $value) {
                $array[$key] = $this->object_array($value);
            }
        }
        return $array;
    }

    /**
     * 获取token并放入令牌桶
     * @param int $uid
     * @param array|null $user
     * @param string $type
     * @return string
     */
    public function createToken(int $uid, ?array $user = null, string $type = ''): string
    {
        $tokenInfo = $this->getToken($uid, $user, $type);
        $exp = $tokenInfo['params']['exp'] - $tokenInfo['params']['iat'] + 60;
        Cache::store('redis')->set(md5('apiToken:' . $uid), ['uid' => $uid, 'type' => $type, 'token' => $tokenInfo['token'], 'exp' => $exp, 'user' => $tokenInfo['params']['user']], (int)$exp);
        return $tokenInfo['token'];
    }
}
